package cn.edu.zut.mock;

import cn.edu.zut.bean.Passenger;
import com.github.javafaker.Faker;

import java.sql.*;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class PassengerDataGenerator {
    private static final String DB_URL = "jdbc:mysql://hadoop102:3306/driver?allowPublicKeyRetrieval=true&useSSL=false&requireSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "000000";
    private static final int BATCH_SIZE = 100;

    public static void main(String[] args) {
        // 默认生成10条数据
        int count = 10;

        // 默认从1天前开始
        LocalDateTime startTime = LocalDateTime.now().minusDays(1);

        // 到现在为止
        LocalDateTime endTime = LocalDateTime.now();

        generateData(count, startTime, endTime);
    }

    public static void generateData(int count, LocalDateTime startTime, LocalDateTime endTime) {
        Faker faker = new Faker(Locale.CHINA);
        List<Passenger> passengers = new ArrayList<>();

        // 获取数据库中已有的最大passenger_id
        long startId = getMaxPassengerId() + 1;

        for (long i = startId; i < startId + count; i++) {
            LocalDateTime createTime = randomLocalDateTime(faker, startTime, endTime);
            // 更新时间在创建时间之后，但不超过当前时间
            LocalDateTime updateTime = randomLocalDateTime(faker,
                    createTime,
                    endTime.isAfter(LocalDateTime.now()) ? LocalDateTime.now() : endTime);

            Passenger passenger = Passenger.builder()
                    .passenger_id(String.valueOf(i))
                    .passenger_name(generateChineseName(faker))
                    .gender(generateRandomGender(faker))
                    .age(faker.number().numberBetween(18, 65))
                    .passenger_phone(generateValidPhoneNumber(faker))
                    .createTime(createTime)
                    .updateTime(updateTime)
                    .build();
            passengers.add(passenger);
        }

        // 批量插入数据库
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            conn.setAutoCommit(false);
            String sql = "INSERT INTO passenger (passenger_id, passenger_name,gender,age,passenger_phone,create_time, update_time) " +
                    "VALUES (?, ?, ?, ?, ?, ?, ?)";

            try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
                for (int i = 0; i < passengers.size(); i++) {
                    Passenger passenger = passengers.get(i);
                    pstmt.setString(1, passenger.getPassenger_id());
                    pstmt.setString(2, passenger.getPassenger_name());
                    pstmt.setString(3, passenger.getGender());
                    pstmt.setInt(4, passenger.getAge());
                    pstmt.setString(5, passenger.getPassenger_phone());
                    pstmt.setTimestamp(6, Timestamp.valueOf(passenger.getCreateTime()));
                    pstmt.setTimestamp(7, Timestamp.valueOf(passenger.getUpdateTime()));
                    pstmt.addBatch();

                    if ((i + 1) % BATCH_SIZE == 0) {
                        pstmt.executeBatch();
                    }
                }
                pstmt.executeBatch();
                conn.commit();
                System.out.println("成功插入" + count + "条乘客数据");
            } catch (SQLException e) {
                conn.rollback();
                e.printStackTrace();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 查询数据库中已有的最大passenger_id
     */
    private static long getMaxPassengerId() {
        String sql = "SELECT MAX(CAST(passenger_id AS SIGNED)) FROM passenger";
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             PreparedStatement pstmt = conn.prepareStatement(sql);
             ResultSet rs = pstmt.executeQuery()) {
            if (rs.next()) {
                return rs.getLong(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0; // 如果表为空，返回0
    }

    /**
     * 随机生成性别：男 / 女 / 保密
     */
    public static String generateRandomGender(Faker faker) {
        String[] genders = {"男", "女", "保密"};
        return genders[faker.random().nextInt(genders.length)];
    }

    private static String generateValidPhoneNumber(Faker faker) {
        // 生成符合中国手机号规则的号码
        String[] prefixes = {"130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
                "145", "147", "150", "151", "152", "153", "155", "156", "157", "158", "159",
                "170", "171", "172", "173", "175", "176", "177", "178", "180", "181", "182",
                "183", "184", "185", "186", "187", "188", "189", "198", "199"};
        String prefix = prefixes[faker.random().nextInt(prefixes.length)];
        String suffix = String.format("%08d", faker.random().nextInt(100000000));
        return prefix + suffix;
    }

    /**
     * 生成符合中文姓名规则的姓名（姓 + 名），总长度为 2 或 3 个字
     */
    public static String generateChineseName(Faker faker) {
        // 常见姓氏
        String[] surnames = {"赵", "钱", "孙", "李", "周", "吴", "郑", "王", "冯", "陈",
                "褚", "卫", "蒋", "沈", "韩", "杨", "朱", "秦", "尤", "许"};

        // 常见双字名的一部分（也可以是单字名）
        String[] firstNames = {"伟", "芳", "娜", "敏", "晓丽", "强", "磊", "静怡", "思琪", "洋", "涛", "静",
                "明", "勇刚", "娟", "平", "浩", "飞雪", "雪峰", "红", "雨桐", "燕", "飞", "小静", "美美",
                "淑娟", "桂英", "文杰", "志刚", "佳", "浩然", "子轩", "梓涵"};

        // 随机选择姓氏
        String surname = surnames[faker.random().nextInt(surnames.length)];
        String firstName = firstNames[faker.random().nextInt(firstNames.length)];

        return surname + firstName;
    }

    private static LocalDateTime randomLocalDateTime(Faker faker, LocalDateTime start, LocalDateTime end) {
        ZonedDateTime startZoned = start.atZone(ZoneId.systemDefault());
        ZonedDateTime endZoned = end.atZone(ZoneId.systemDefault());

        long startEpoch = startZoned.toInstant().toEpochMilli();
        long endEpoch = endZoned.toInstant().toEpochMilli();

        long randomEpoch = faker.date().between(
                new Date(startEpoch),
                new Date(endEpoch)
        ).getTime();

        return LocalDateTime.ofInstant(
                java.time.Instant.ofEpochMilli(randomEpoch),
                ZoneId.systemDefault()
        );
    }
}